#include <stdlib.h>
#include <stdio.h>
#include "../common.h"
#include "bitboard.h"
#include "bitboard_init.h"

#if 0
int first_one(int x, int s)
{
	s <<= 3;
	return x != 0 ? (s - 1) - (__builtin_clz(x) - ((sizeof(int)<<3) - s)) : s;
}

int last_one(int x)
{
	return x != 0 ? __builtin_ctz(x) : -1;
}

int last_one_64(bitboard x)
{
//	int l;

//	if ((l = last_one(x)) != -1) {
//		return l;
//	} else {
//		return 32 + last_one(x >> 32);
//	}

	return x != 0 ? __builtin_ctzll(x) : -1;
}

uint8_t get_rank_contents(bitboard b, int c)
{
	uint8_t contents;

	contents = 0xFF & (b >> (c & ~0x07));

	return contents;
}

uint8_t get_file_contents(bitboard b, int c)
{
	uint8_t contents;

	contents = 0xFF & (b >> (coord_map_rl90[c] & ~0x07));

	return contents;
}


uint8_t get_diag_contents(bitboard b, int c, int *map)
{
	uint8_t contents;
	int sr;

	switch (map[c]) {
	case 0:
		sr = 0;
		break;
	case 1: case 2:
		sr = 1;
		break;
	case 3: case 4: case 5:
		sr = 3;
		break;
	case 6: case 7: case 8: case 9:
		sr = 6; 
		break;
	case 10: case 11: case 12: case 13:
	case 14:
		sr = 10;
		break;
	case 15: case 16: case 17: case 18:
	case 19: case 20:
		sr = 15;
		break;
	case 21: case 22: case 23: case 24:
	case 25: case 26: case 27:
		sr = 21;
		break;
	case 28: case 29: case 30: case 31:
	case 32: case 33: case 34: case 35:
		sr = 28;
		break;
	case 36: case 37: case 38: case 39:
	case 40: case 41: case 42:
		sr = 36;
		break;
	case 43: case 44: case 45: case 46:
	case 47: case 48:
		sr = 43;
		break;
	case 49: case 50: case 51: case 52:
	case 53:
		sr = 49;
		break;
	case 54: case 55: case 56: case 57:
		sr = 54;
		break;
	case 58: case 59: case 60:
		sr = 58;
		break;
	case 61: case 62:
		sr = 61;
		break;
	case 63: default:
		sr = 63;
		break;
	}
	
	contents = 0xFF & (b >> sr);

	return contents;
}

bitboard get_piece_board(board_t *b, int color, int piece)
{
	switch (piece) {
	case PAWN:
		return b->color[color].pawns;
	case KNIGHT:
		return b->color[color].knights;
	case KING:
		return b->color[color].king;
	case BISHOP:
		return b->color[color].bishops;
	case ROOK:
		return b->color[color].rooks;
	case QUEEN:
		return b->color[color].queens;
	default:
		return 0;
	}
}

bitboard *get_piece_board_p(board_t *b, int color, int piece)
{
	switch (piece) {
	case PAWN:
		return &(b->color[color].pawns);
	case KNIGHT:
		return &(b->color[color].knights);
	case KING:
		return &(b->color[color].king);
	case BISHOP:
		return &(b->color[color].bishops);
	case ROOK:
		return &(b->color[color].rooks);
	case QUEEN:
		return &(b->color[color].queens);
	default:
		return NULL;
	}
}


int get_piece_type(board_t *b, int sq, int color)
{
	if (!(b->color[color].all & piece_setmask[sq])) {
		return 0;
	} else if (b->color[color].pawns & piece_setmask[sq]) {
		return PAWN;
	} else if (b->color[color].knights & piece_setmask[sq]) {
		return KNIGHT;
	} else if (b->color[color].king & piece_setmask[sq]) {
		return KING;
	} else if (b->color[color].bishops & piece_setmask[sq]) {
		return BISHOP;
	} else if (b->color[color].rooks & piece_setmask[sq]) {
		return ROOK;
	} else if (b->color[color].queens & piece_setmask[sq]) {
		return QUEEN;
	} else {
		return -1;
	}
}

int get_piece_color(board_t *b, int sq)
{
	return (b->color[WHITE].all & piece_setmask[sq]) == 0;
}

#endif

void display_bitboard(FILE *of, bitboard b)
{
	int r, f;
	uint8_t rank;

	fprintf(of, "   A B C D E F G H\n");
	fprintf(of, "  -----------------  \n");

	for (r=0; r<8; r++) {
		rank = b >> ((7-r)<<3); // start with rank 8, work down to rank 1
		fprintf(of, "%d ", 8-r);
		for (f=0; f<8; f++) {
			fprintf(of, "|%c", (rank & 0x01) ? 'X' : ' '); // file A to H == bit 0 to 7
			rank >>= 1;
		}
		fprintf(of, "| %d\n  -----------------\n", 8-r);
	}
	fprintf(of, "   A B C D E F G H\n");
}

void print_board(FILE *of, board_t *b)
{
	int r, f, sq;
	int piece, color;
	char wp[8] = {' ', 'P', 'N', 'K', ' ', 'B', 'R', 'Q'};
	char bp[8] = {' ', 'p', 'n', 'k', ' ', 'b', 'r' ,'q'};

	fprintf(of, "   A B C D E F G H\n");
	fprintf(of, "  -----------------  \n");

	for (r=7; r>=0; r--) {
		fprintf(of, "%d ", r+1);
		for (f=0; f<8; f++) {
			sq = C2N(r,f);
			//color = (b->color[WHITE].all & piece_setmask[sq]) == 0;
			color = get_piece_color(b, sq);
			piece = get_piece_type(b, sq, color);
			fprintf(of, "|%c", color == WHITE ? wp[piece] : bp[piece]);
		}
		fprintf(of, "| %d\n  -----------------\n", r+1);
	}
	fprintf(of, "   A B C D E F G H\n");
}


